using Jupiter.Infrastructure.Attributes;
using Jupiter.Infrastructure.Cache.Interfaces;
using Jupiter.Infrastructure.Domain.SqlSugar;
using Jupiter.Infrastructure.Exceptions;
using Jupiter.Infrastructure.Permission;
using Jupiter.Infrastructure.Permission.DataPermissions;
using Jupiter.Infrastructure.Responses;
using Microsoft.Extensions.Configuration;
using Wips.AppService.Authorities.Menus;
using Wips.AppService.Authorities.Operations;
using Wips.AppService.Authorities.Roles.ViewModels;
using Wips.AppService.Authorities.Users;
using Wips.AppService.Authorities.Users.Requests;
using Wips.AppService.Authorities.Users.Responses;
using Wips.AppService.Authorities.Users.ViewModels;
using Wips.AppService.CommonViewModels;
using Wips.Domain.Models.Authorities.Model;

namespace Wips.AppService.SqlSugar.Authorities.Users
{
    /// <summary>
    /// 用户服务接口实现类
    /// </summary>
    [ServiceComponent]
    public class UserService : BaseQueryAppService<User>, IUserService
    {
        private readonly ISecurityContextAccessor _securityContextAccessor;

        private readonly ICacheManager _cacheManager;

        private readonly IMenuService _menuService;


        private readonly IOperationService _operationService;

        /// <summary>
        /// 读取分页列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<PageResult<GetUserPagesResponse>> GetPagesAsync(
            GetUserPagesRequest request)
        {
            List<string?> allOrganizationList = new List<string?>();
            if (!string.IsNullOrEmpty(request.OrganizationId))
            {
                // 拿出当前组织架构和子组织架构的id
                allOrganizationList = await QueryNoTracking<Organization>()
                    .Where(c => c.ParentPath.Contains(request.OrganizationId)
                                || c.Id == request.OrganizationId
                    )
                    .Select(c => c.Id)
                    .ToListAsync();
            }

            var result = await QueryNoTracking()

                .HasWhere(request.Keyword, user =>
                    user.UserName.Contains(request.Keyword!) ||
                    user.RealName.Contains(request.Keyword!) ||
                    user.PhoneNumber.Contains(request.Keyword!) ||
                    user.Email.Contains(request.Keyword!)
                )
                .HasWhere(request.OrganizationId,
                    user => user.OrganizationUsers.Any(c => allOrganizationList.Contains(c.OrganizationId)))
                .HasWhere(request.Filter.Status != null,
                    user => request.Filter.Status!
                        .Select(e => (Status)Convert.ToInt32(e))
                        .Contains(user.Status))
                .Select(user => new GetUserPagesResponse
                {
                    Id = user.Id!,
                    UserName = user.UserName,
                    RealName = user.RealName,
                    PhoneNumber = user.PhoneNumber,
                    Email = user.Email,
                    Status = user.Status,
                    Created = user.Created,
                    Updated = user.Updated,
                    CreatorId = user.CreatorId,

                    OwnerId = "",
                    TrueOrFalse = false,
                    JobId = "",
                    OrganizationId = "",
                    ProjectId = ""
                })
                .ToPageAsync(request);

            if (!result.HasItems())
            {
                return result;
            }

            //获取当页的所有用户Id
            var userIds = result.Items.Select(p => p.Id).ToList();

            // 读取角色
            var roles = await QueryNoTracking<UserRole>()
                .Includes(p => p.Role)
                .Where(p => userIds.Contains(p.UserId))
                .Where(p => p.Role.RoleType == EnumRoleType.Admin)
                .ToListAsync();

            // 职位
            var positions = await QueryNoTracking<PositionUser>()
                .Includes(p => p.Position)
                .Where(p => userIds.Contains(p.UserId))
                .ToListAsync();
            // 组织架构
            var organizations = await QueryNoTracking<OrganizationUser>()
                .Includes(p => p.Organization)
                .Where(p => userIds.Contains(p.UserId))
                .ToListAsync();



            foreach (var item in result.Items)
            {

                //角色
                var tempRoles = roles.Where(p => p.UserId == item.Id)
                    .ToList();
                if (tempRoles.Count > 0)
                {
                    List<string> roleNames;
                    roleNames = tempRoles.Where(p => p.Role != null).Select(p => p.Role.Name).ToList();
                    if (roleNames.Count == 0) roleNames.Add("管理员");
                    item.RoleNames.AddRange(roleNames);
                }

                // 职位
                var tempPositions = positions.Where(p => p.UserId == item.Id)
                    .ToList();
                if (tempPositions.Count > 0)
                {
                    var positionNames = tempPositions.Select(p => p.Position.Name).ToList();
                    item.PositionNames.AddRange(positionNames);
                }

                // 组织架构
                var tempOrganizations = organizations.Where(p => p.UserId == item.Id)
                    .ToList();
                if (tempOrganizations.Count > 0)
                {
                    var organizationNames = tempOrganizations.Select(p => p.Organization.Name).ToList();
                    item.OrganizationNames.AddRange(organizationNames);
                }
            }


            return result;
        }

        /// <summary>
        /// 读取信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<GetUserByIdResponse> GetByIdAsync(string? id)
        {
            if (string.IsNullOrEmpty(id))
            {
                if (string.IsNullOrEmpty(_securityContextAccessor.UserId))
                {
                    throw new CoreException("用户未登录");
                }

                // 当前登录用户
                id = _securityContextAccessor.UserId;
            }

            var result = await QueryNoTracking()
                .Where(p => p.Id == id)
                .Select(p => new GetUserByIdResponse
                {
                    Id = p.Id!,
                    UserName = p.UserName,
                    RealName = p.RealName,
                    PhoneNumber = p.PhoneNumber,
                    Email = p.Email,
                    Status = p.Status,
                })
                .FirstOrDefaultAsync();

            if (result == null)
            {
                throw new CoreException("找不到数据");
            }



            // 读取角色
            var roles = await QueryNoTracking<UserRole>()
                .Where(p => p.Role.TenantId == TenantId ||
                            p.Role.RoleType == EnumRoleType.Admin)
                .Where(p => p.UserId == id)
                .Select(p => p.RoleId).ToListAsync();

            result.RoleIds.AddRange(roles);
            // 职位
            var positions = await QueryNoTracking<PositionUser>()
                .Where(p => p.UserId == id)
                .Select(p => p.PositionId).ToListAsync();

            result.PositionIds.AddRange(positions);
            // 组织架构
            var organizations = await QueryNoTracking<OrganizationUser>()
                .Where(p => p.UserId == id)
                .Select(p => p.OrganizationId).ToListAsync();

            result.OrganizationIds.AddRange(organizations);



            return result;
        }


        /// <summary>
        /// 读取信息
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public async Task<GetUserByUserNameResponse> GetByUserNameAsync(string userName)
        {
            var result = await Query()
                .Where(p => p.UserName == userName)
                .Select(p => new GetUserByUserNameResponse
                {
                    Id = p.Id!,
                    UserName = p.UserName,
                    RealName = p.RealName,
                    Password = p.Password,
                    PhoneNumber = p.PhoneNumber,
                    Email = p.Email,
                    Status = p.Status
                })
                .FirstOrDefaultAsync();

            if (result == null)
            {
                throw new CoreException("找不到数据");
            }


            // 读取组织架构用户
            var organizationIds = await QueryNoTracking<OrganizationUser>()
                .Where(p => p.UserId == result.Id)
                .Select(p => p.OrganizationId)
                .ToListAsync();
            // 组织架构Id
            var organizationIdList = new List<string?>();
            // 读取下级组织架构Id列表
            foreach (var organizationId in organizationIds)
            {
                var itemIds = await QueryNoTracking<Organization>() //解决排除获取为空的企业ID过滤器
                    .Where(p => p.ParentPath.Contains(organizationId))
                    .Select(p => p.Id)
                    .ToListAsync();
                if (itemIds.Count > 0)
                {
                    organizationIdList.AddRange(itemIds);
                }
            }

            var userRoleIds = await GetUserRoleSql(result.Id);
            // 读取角色你信息
            var roles = await QueryNoTracking<Role>()
                .Where(a =>
                    userRoleIds!.Contains(a.Id!)
                )
                .Select(p => new RoleViewModel
                {
                    Id = p.Id!,
                    Name = p.Name
                })
                .ToListAsync();
            result.Roles.AddRange(roles);
            result.OrganizationIds = organizationIdList!;
            return result;
        }


        /// <summary>
        /// 读取信息 - 当前登录人
        /// </summary>
        /// <returns></returns>
        public async Task<GetUserByUserNameResponse> GetByTokenAsync()
        {
            var result = await Query()
                .Where(p => p.Id == UserId)
                .Select(p => new GetUserByUserNameResponse
                {
                    Id = p.Id!,
                    UserName = p.UserName,
                    RealName = p.RealName,
                    Password = p.Password,
                    PhoneNumber = p.PhoneNumber,
                    Email = p.Email,
                    Status = p.Status,
                })
                .FirstOrDefaultAsync();

            if (result == null)
            {
                throw new CoreException(401, "找不到数据");
            }



            return result;
        }

        /// <summary>
        /// 读取信息
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="smsCode"></param>
        /// <returns></returns>
        /// <exception cref="CoreException"></exception>
        public async Task<GetUserByUserNameResponse> GetByUserNameAsync(string userName, string smsCode)
        {
            if (!string.IsNullOrEmpty(smsCode))
            {
                var smsKey = string.Format("SMSSENDKEY:{0}:{1}", userName, 1);
                var code = await _cacheManager.GetStringAsync(smsKey);

                Jupiter.Infrastructure.Check.Validate<CoreException>(string.IsNullOrEmpty(code), "请先点击发送短信验证码！");
                Jupiter.Infrastructure.Check.Validate<CoreException>(code != smsCode, "短信验证码错误！");
            }
            else
            {
                throw new CoreException("短信验证码不可为空");
            }

            return await GetByUserNameAsync(userName);
        }


        /// <summary>
        /// 根据角色Id读取用户列表
        /// </summary>
        /// <param name="roleId">角色Id</param>
        /// <returns></returns>
        public async Task<List<string>> GetIdsByRoleIdAsync(string roleId)
        {
            var list = new List<string>();
            var userIds = await QueryNoTracking<UserRole>()
                .Where(p => p.RoleId == roleId)
                .Select(p => p.UserId)
                .ToListAsync();
            list.AddRange(userIds);
            var organizationIds = SqlFunc.Subqueryable<OrganizationRole>()
                .Where(p => p.RoleId == roleId)
                .Select(p => p.OrganizationId);

            var userIds1 = await QueryNoTracking<OrganizationUser>()
                .Where(p => organizationIds == p.OrganizationId)
                .Select(p => p.UserId)
                .ToListAsync();
            list.AddRange(userIds1);

            var positionIds = SqlFunc.Subqueryable<PositionRole>()
                .Where(p => p.RoleId == roleId)
                .Select(p => p.PositionId);

            var userIds2 = await QueryNoTracking<PositionUser>()
                .Where(p => positionIds == p.PositionId)
                .Select(p => p.UserId)
                .ToListAsync();
            list.AddRange(userIds2);

            var result = list.GroupBy(userId => userId)
                .Select(userId => userId.FirstOrDefault())
                .ToList();

            if (result.Count == 0)
            {
                throw new CoreException("该角色下无用户信息");
            }

            return result!;
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="CoreException"></exception>
        public async Task<GetUserResponse> GetUserAsync(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                if (string.IsNullOrEmpty(_securityContextAccessor.UserId))
                {
                    throw new CoreException("用户未登录");
                }

                // 当前登录用户
                id = _securityContextAccessor.UserId;
            }

            var result = await QueryNoTracking()
                .Where(p => p.Id == id)
                .Select(p => new GetUserResponse
                {
                    Id = p.Id!,
                    UserName = p.UserName,
                    RealName = p.RealName,
                    PhoneNumber = p.PhoneNumber,
                    Email = p.Email,
                    Status = p.Status,
                })
                .FirstOrDefaultAsync();

            if (result == null)
            {
                throw new CoreException("找不到数据");
            }

            return result;
        }

        /// <summary>
        /// 读取树形选择框数据列表(系统用户)
        /// </summary>
        /// <returns></returns>
        public async Task<List<SelectViewModel>> GetSelectDataAsync()
        {
            var result = await QueryNoTracking().Where(p => p.Status == Status.Enabled)
                .Select(t1 => new SelectViewModel
                {
                    Id = t1.Id!,
                    Label = t1.RealName,
                    Value = t1.Id!,
                    Key = t1.Id!,
                    Disabled = t1.Status == Status.Disabled,
                })
                .ToListAsync();

            return result;
        }

        /// <summary>
        /// 读取树形选择框数据列表（渠道用户）
        /// </summary>
        /// <returns></returns>
        public async Task<List<SelectViewModel>> GetSelectForChannelUserDataAsync()
        {
            var result = await QueryNoTracking().Where(p => p.Status == Status.Enabled)
                .Select(t1 => new SelectViewModel
                {
                    Id = t1.Id!,
                    Label = t1.RealName,
                    Value = t1.Id!,
                    Key = t1.Id!,
                    Disabled = t1.Status == Status.Disabled,
                })
                .ToListAsync();

            return result;
        }



        /// <summary>
        /// 获取账号菜单数据
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<UserAuthorityModel> GetAccountEnterprise(string userId)
        {

            // 获取菜单授权
            var menuViewModel = await _menuService.GetRoutePathAsync(userId);

            // 获取权限授权
            var operationModel = await _operationService.GetVersionsOperationAsync(userId);

            var result = new UserAuthorityModel();
            result.RoutePaths = menuViewModel.Select(c => c.Path).Concat(menuViewModel.Select(c => c.ParentPath))
                .Where(c => !string.IsNullOrEmpty(c))
                .Distinct()
                .ToList();
            result.OperationCodes = operationModel.Select(c => c.Code)
                .Where(c => !string.IsNullOrEmpty(c))
                .SelectMany(c => c.Split(","))
                .Distinct()
                .ToList();
            return result;




        }


        /// <summary>
        /// 获取Root账号菜单数据
        /// </summary>
        /// <returns></returns>
        public async Task<UserAuthorityModel> GetRootAccountEnterprise()
        {

            // 获取菜单授权
            var menuViewModel = await _menuService.GetRoutePathAsync("root", true);


            // 获取权限授权
            var operationModel = await _operationService.GetVersionsOperationAsync("root", true);


            var result = new UserAuthorityModel();
            result.RoutePaths = menuViewModel.Select(c => c.Path).Concat(menuViewModel.Select(c => c.ParentPath))
                .Where(c => !string.IsNullOrEmpty(c))
                .Distinct()
                .ToList();
            result.OperationCodes = operationModel.Select(c => c.Code)
                .Where(c => !string.IsNullOrEmpty(c))
                .SelectMany(c => c.Split(","))
                .Distinct()
                .ToList();
            return result;


        }





        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="securityContextAccessor"></param>
        /// <param name="configuration"></param>
        /// <param name="cacheManager"></param>
        /// <param name="dataPermission"></param>
        public UserService(ISqlSugarClient dbContext, ISecurityContextAccessor securityContextAccessor,
            IConfiguration? configuration, ICacheManager cacheManager, IDataPermission? dataPermission, IMenuService menuService, IOperationService operationService) : base(
            dbContext,
            securityContextAccessor, configuration, cacheManager, dataPermission)
        {
            _securityContextAccessor = securityContextAccessor;
            _cacheManager = cacheManager;
            _menuService = menuService;
            _operationService = operationService;
        }
    }
}